package com.pine.dcts.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pine.dcts.common.DctsConstant;
import com.pine.dcts.common.DctsException;
import com.pine.dcts.entity.Org;
import com.pine.dcts.mapper.OrgMapper;
import com.pine.dcts.service.OrgService;

import com.pine.dcts.utils.TreeUtils;
import org.apache.commons.lang3.StringUtils;

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

/**
 * @author xiaoyuan
 * @create 2020/11/23 14:12
 **/
@Service
public class OrgServiceImpl extends ServiceImpl<OrgMapper, Org> implements OrgService {

    /**
     * 对象缓存名称
     */
    private static final String _CACHE_NAME = "org:cache:";


    @Override
    public List<Org> tree(String name) {
        LambdaQueryWrapper<Org> wrapper = new LambdaQueryWrapper<>();
        wrapper.ne(Org::getStatus, -1);
        if (StringUtils.isNotEmpty(name)) {
            wrapper.like(Org::getName, name);
        }
        List<Org> orgs = this.baseMapper.selectList(wrapper);
        List<Org> treeList = TreeUtils.getTreeList(null, orgs);
        return treeList;
    }

    @Cacheable(value = _CACHE_NAME + "tree")
    @Override
    public List<Org> enabledTree() {
        LambdaQueryWrapper<Org> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Org::getStatus, DctsConstant.YES);
        List<Org> orgs = this.baseMapper.selectList(wrapper);
        List<Org> treeList = TreeUtils.getTreeList(null, orgs);
        return treeList;
    }

    @Cacheable(value = _CACHE_NAME + "id:", key = "#id")
    @Override
    public Org getById(Serializable id) {
        return super.getById(id);
    }


    @CacheEvict(value = {_CACHE_NAME + "tree",_CACHE_NAME + "name:"}, allEntries = true)
    @Transactional
    @Override
    public boolean save(Org entity) {
        if (!checkName(entity)) {
            throw new DctsException("机构名称已存在");
        }
        if (!checkCode(entity)) {
            throw new DctsException("机构编码已存在");
        }
        return super.save(entity);
    }

    /**
     * @Description: 只做逻辑删除
     * @Author: xiaoyuan
     * @Date: 2020/10/20 11:15
     */
    @CacheEvict(value = {_CACHE_NAME + "tree",_CACHE_NAME + "name:"}, allEntries = true)
    @Transactional
    @Override
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        idList.forEach(id -> {
            if (!checkChildren(Integer.valueOf((String) id))) {
                throw new DctsException("该机构下存在子机构，请先删除子机构后操作");
            }
            Org org = new Org();
            org.setId(Integer.valueOf((String) id));
            org.setStatus(-1);
            this.baseMapper.updateById(org);
        });
        return true;
    }

    @CacheEvict(value = {_CACHE_NAME + "tree",_CACHE_NAME + "name:"}, allEntries = true)
    @Transactional
    @Override
    public boolean updateById(Org entity) {
        if (!checkName(entity)) {
            throw new DctsException("机构名称已存在");
        }
        if (!checkCode(entity)) {
            throw new DctsException("机构编码已存在");
        }
        return super.updateById(entity);
    }


    /**
     * 检查配置项是否有重复
     *
     * @param entity
     * @return
     */
    private boolean checkName(Org entity) {
        LambdaQueryWrapper<Org> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Org::getName, entity.getName());
        if (entity.getId() != null) {
            wrapper.ne(Org::getId, entity.getId());
        }
        if (entity.getParentId() != null) {
            wrapper.ne(Org::getParentId, entity.getParentId());
        }
        return this.list(wrapper).size() == 0;
    }


    /**
     * 检查配置项是否有重复
     *
     * @param entity
     * @return
     */
    private boolean checkCode(Org entity) {
        LambdaQueryWrapper<Org> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Org::getCode, entity.getCode());
        if (entity.getId() != null) {
            wrapper.ne(Org::getId, entity.getId());
        }
        return this.list(wrapper).size() == 0;
    }

    private boolean checkChildren(Integer id) {
        LambdaQueryWrapper<Org> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Org::getParentId, id);
        return this.baseMapper.selectCount(wrapper) == 0;
    }
}
